Enunciado

Bienvenidos a la Actividad 1, donde pondremos en práctica todo lo aprendido durante el bloque 2. Esta actividad la realizaremos en clase, se terminará en casa (debería completarse en clase) y se entregará el día 8 de octubre.

¿En qué consiste?

Vamos a poner en práctica cuatro aspectos del procesamiento de imágenes:

La finalidad es sencilla. Se os dará una imagen, a color, que tiene varias tonalidades y que está pintada con círculos.

La actividad consiste en contar el número de círculos de la imagen. image.png

Evaluación

Se evaluará de la siguiente manera:

Formato de entrega

No se aceptará el formato .ipynb Habilitaré una actividad en Canvas para que podáis subir ambos archivos.

Inicialización

En primer lugar, cargamos todos los paquetes/frameworks que nos van a hacer falta. Se recomienda visitar la web: https://scikit-image.org/ para ver todas las funcionalidades que permite Scikit Image.

Cargar la imagen

Lo primero de todo, vamos a leer la imagen. Recuerda que hay que subir la imagen cada vez que inicies sesión en el notebook y que la ruta se mira haciendo botón derecho sobre el archivo.

Con lo cual, aquí vamos a hacer dos cosas:

Hacemos esto para luego posteriormente umbralizar la imagen en escala de grises.

Umbralizar la imagen con varios métodos

Vamos a probar ahora diferentes métodos para umbralizar la imagen. Se pide en esta actividad:

Método OTSU: Calcula automáticamente un umbral óptimo para separar los objetos de interés del fondo en una imagen en escala de grises.

Método de Niblack: Divide la imagen en pequeñas ventanas o bloques y calcula un umbral local para cada bloque.

Podemos observar que cambia mucho el resultado dependiendo el tamaño de la ventana que pongamos; es decir para números pequeños se ve con mejor calidad la imagen que con los números grandes.

Método de Local: Los métodos locales suelen utilizarse para resaltar características específicas, reducir el ruido o adaptar el procesamiento a variaciones locales en la imagen.

Es mejor usar bloque grande para que se defina mejor la imagen quitando el ruido.

Método de Sauvola: Al igual que Niblack, divide la imagen en bloques y calcula umbrales locales. Sin embargo, Sauvola utiliza un enfoque adaptativo que tiene en cuenta la media y la desviación estándar locales de la intensidad de los píxeles, lo que lo hace robusto frente a cambios en la iluminación y el contraste local.

El método que mas se parece al resultado que hay que alcanzar, es el Método Local. Es por ello que voy a coger el Local para seguir realizando el trabajo ya que se perciben mejor los puntos para proceder a contarlos.

Morfología Matemática

Como se puede apreciar en la imagen hay varios elementos imperfectos:

Mediante el uso de morfología matemática (concretamente los cuatro operadores visto en clase) y los posibles elementos estructurales existentes, se pide:

Aplicando el elemento estructural DISK

Erosión: El resultado es que la erosión tiende a eliminar detalles pequeños, eliminar ruido y reducir el tamaño de los objetos en una imagen.

Dilatación: El resultado es que la dilatación aumenta el tamaño de los objetos en una imagen y llena agujeros pequeños o separaciones en las regiones.

Apertura: La apertura es una operación morfológica en procesamiento de imágenes que combina dos operaciones morfológicas básicas: la erosión seguida de la dilatación.

Clausura: La clausura (también conocida como cierre) es una operación morfológica en procesamiento de imágenes que se utiliza para completar y cerrar pequeños agujeros o huecos en objetos en una imagen.

Aplicando el elemento estructural Diamond

Erosión

Dilatación

Apertura

Clausura

Como he comentado anteriormente el método local es el ideal para contar los círculos. Previamente después de haber aplicado los diferentes filtros podemos observar: que con el elemento Disk la imagen empeorá y no desparacen la gran mayoría de puntos, por tanto, no es útil a la hora de contar; en cambio con el elemento Diamond podemos observar que se cuentan más facilmente los puntos, sobretodo con el filtro de apertura.

Contando círculos

Haciendo uso de las funcionalidades cargadas al principio, se pide hacer una función que:

Por último, ¿qué se podría hacer para asegurar que no se tienen en cuenta posibles errores en la umbralización como pequeños puntos o posible ruido que haya llegado hasta este punto?

Conversión de la imagen Local en binaria

Conversión de la Imagen de Apertura (diamante) en binaria

Conversión Imagen Apertura (Disk) en binaria

Comprobación de matrices (local y apertura)

Contamos los círculos (local y apertura)

Imagen Local

Imagen Apertura (diamantes)

Conclusión: Como podemos observar se obtiene mejor resultado usando la imagen Local sin ningún filtro, que usando apertura con el filtro diamante debido a que el número de conteo es menor en este último. Por tanto, concluimos con que la imagen es más util sin filtro que con el filtro diamond. Ahora probamos el filtro Disk para compararlo con el Diamond.

Imagen Apertura (Disk)

Como podemos observar en comparación con el elemento Diamante, es mejor el elemento Disk (tiene sentido ya que en este tipo de imagen lo que queremos es contar elementos circulares), por tanto es mejor Disk. As u vez, hemos podido observar que también es mejor la imagen con el elemento Disk y el filtro Apertura que incluso la propia imagen Local que al principio nos parecía la idonea.

(Bonus) Automatizamos el proceso de extracción

Esta sección no es obligatoria pero la pongo para aquellos que quieran saber "¿y ahora qué se haría?".

Lo que hemos hecho hasta ahora es:

Es decir, tenemos varios parámetros y tenemos una función que nos dice cuál es el número de puntos dada una imagen. Variando dichos parámetros, variará también el número de puntos, pero no parece haber una relación directa.

También no hay que olvidar que desconocemos el número de puntos (nunca se ha dicho, aunque siempre puedes contarlos), por lo que no podemos seguir un proceso de aprendizaje supervisado (tipo descenso del gradiente sobre los parámetros anteriores para encontrar el mejor resultado).

Pero lo que sí podemos hacer es iterar el valor de los parámetros para alcanzar un máximo de puntos (asumiendo que dicho máximo corresponderá con el mejor resultado). Esto suele hacerse cuando no sabemos exáctamente el resultado que esperamos.

En definitiva, ahora se buscaría realizar un proceso iterativo para encontrar el valor máximo del número de puntos. Para ello haría falta:

Podría decirse que esa combinación de parámetros es la mejor.

Este es el resultado del código, el número ideal de puntos es 1991 todo basado en la imagen binaria de la escala de grises. El kernel debe sr 7 y el umbral 140.